package com.ncmmall.api.apis.mall;

import cn.hutool.core.date.DateUtil;
import com.ncmmall.api.apis.service.Result;
import com.ncmmall.api.params.MerchantShoppingCartGoodsDTO;
import com.ncmmall.api.params.OrderPreviewDTO;
import com.ncmmall.api.params.ShopCartDTO;
import com.ncmmall.api.security.Securitys;
import com.ncmmall.application.business.order.OrderApplication;
import com.ncmmall.application.util.HttpRequests;
import com.feijin.commons.exceptions.InterfaceException;
import com.feijin.commons.lang.ArithUtils;
import com.feijin.commons.lang.Requires;
import com.feijin.commons.securitys.MD5HashUtils;
import com.ncmmall.domain.business.deliveryaddress.DeliveryAddress;
import com.ncmmall.domain.business.deliveryaddress.QDeliveryAddress;
import com.ncmmall.domain.business.express.Express;
import com.ncmmall.domain.business.express.QExpress;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.goods.channel.GoodsChannel;
import com.ncmmall.domain.business.goods.sku.GoodsSku;
import com.ncmmall.domain.business.goods.sku.QGoodsSku;
import com.ncmmall.domain.business.marketing.coupon.Coupon;
import com.ncmmall.domain.business.marketing.gift.GiftActivity;
import com.ncmmall.domain.business.marketing.gift.GiftChannel;
import com.ncmmall.domain.business.marketing.gift.GiftScope;
import com.ncmmall.domain.business.marketing.gift.QGiftActivity;
import com.ncmmall.domain.business.marketing.gift.QGiftChannel;
import com.ncmmall.domain.business.marketing.gift.QGiftScope;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardAddress;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardGoods;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardMerchant;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardRecord;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCard;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardAddress;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardGoods;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardMerchant;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardRecord;
import com.ncmmall.domain.business.merchant.freight.MerchantFreight;
import com.ncmmall.domain.business.merchant.freight.MerchantFreightTemplate;
import com.ncmmall.domain.business.merchant.freight.QMerchantFreight;
import com.ncmmall.domain.business.merchant.freight.QMerchantFreightTemplate;
import com.ncmmall.domain.business.order.Order;
import com.ncmmall.domain.business.order.OrderDetail;
import com.ncmmall.domain.business.order.QOrder;
import com.ncmmall.domain.business.order.aftersale.OrderAfterSale;
import com.ncmmall.domain.business.order.aftersale.QOrderAfterSale;
import com.ncmmall.domain.business.order.dto.OrderDTO;
import com.ncmmall.domain.business.order.groupbooking.GroupBooking;
import com.ncmmall.domain.business.order.groupbooking.GroupBookingOrder;
import com.ncmmall.domain.business.order.groupbooking.QGroupBookingOrder;
import com.ncmmall.domain.business.order.lading.BillOfLading;
import com.ncmmall.domain.business.setting.CancelCause;
import com.ncmmall.domain.business.setting.QCancelCause;
import com.ncmmall.domain.business.shoppingcart.QShoppingCart;
import com.ncmmall.domain.business.shoppingcart.ShoppingCart;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单模块相关的API接口
 *
 * @author linxs
 * @date 2019-07-15 17:06
 */
@RestController
@RequestMapping(value = "/order")
@Slf4j
@RequiredArgsConstructor
public class OrderApi {

    private final QueryChannelService queryChannelService;
    private final OrderApplication orderApplication;

    @Value("${store.domain}")
    private String storeDomain;

    /**
     * 订单详情
     *
     * @param id 订单ID
     */
    @GetMapping("/detail")
    public Result detail(HttpServletRequest request, @RequestParam long id) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            Order order = queryChannelService.findOne(QOrder.order.id.eq(id).and(QOrder.order.member.eq(member)), Order.class);

            for (OrderDetail detail : order.getDetails()) {
                detail.setDefaultImage(storeDomain + "/uploads/" + detail.getDefaultImage());
                detail.setGoodsId(detail.getSku().getGoods().getId());
                detail.setBargainStatus(detail.getSku().getGoods().getBargainStatus());
                detail.setGroupBookingStatus(detail.getSku().getGoods().getGroupBookingStatus());
                detail.setSeckillStatus(detail.getSku().getGoods().getSeckillStatus());
                detail.setPresellStatus(detail.getSku().getGoods().getPresellStatus());
                detail.setPresellRetainagePayBeginTime(detail.getSku().getGoods().getPresellRetainagePayBeginTime());
                detail.setPresellRetainagePayEndTime(detail.getSku().getGoods().getPresellRetainagePayEndTime());
                detail.setPresellSubscriptionPayBeginTime(detail.getSku().getGoods().getPresellSubscriptionPayBeginTime());
                detail.setPresellSubscriptionPayEndTime(detail.getSku().getGoods().getPresellSubscriptionPayEndTime());
            }

            if (order.getIsAfterSale() == 1) {
                order.setOrderAfterSaleId(queryChannelService.findOne(QOrderAfterSale.orderAfterSale.order.id.eq(order.getId()), OrderAfterSale.class).getId());
            }

            if (null != order.getCoupon() && null != order.getCoupon().getComplimentaryGoods()) {
                order.getCoupon().getComplimentaryGoods().setDefaultImage(storeDomain + "/uploads/" + order.getCoupon().getComplimentaryGoods().getDefaultImage());
            }

            //赠品活动订单
            setGiftGoods(order);

            order.setCurrentTime(new Timestamp(System.currentTimeMillis()));
            order.setMerchantInfo(ImmutableMap.of("id", order.getMerchant().getId(), "shopName", order.getMerchant().getShopName()));

            return result.ok().inject(order);

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 设置赠品活动订单
     *
     * @param order 订单
     */
    private void setGiftGoods(Order order) {

        if (order.getMarketingType() != 1) {
            return;
        }

        List<Goods> giftGoodses = queryChannelService.findAll("select g.goods from GiftGoods g where g.gift.id = :id ", ImmutableMap.of("id", order.getGiftActivity().getId()), Goods.class);
        GiftActivity giftActivity = order.getGiftActivity();

        giftActivity.setGiftGoodses(giftGoodses.stream().map(input -> {
            Map<String, Object> data = new HashMap<>();
            data.put("id", input.getId());
            data.put("name", input.getName());
            data.put("defaultImage", storeDomain + "/uploads/" + input.getDefaultImage());
            return data;
        }).collect(Collectors.toList()));

    }

    /**
     * 查询订单的所有物流包裹
     *
     * @param id 订单id
     */
    @GetMapping("/queryDelivery")
    public Result queryDelivery(@RequestParam long id) {

        Result result = new Result();
        try {

            Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);

            List<BillOfLading> billOfLadings = queryChannelService.findAll("select b from BillOfLading b where b.order.id = :id and b.status in (3,4) ", ImmutableMap.of("id", id), BillOfLading.class);
            List<Map<String, Object>> data = Lists.newArrayList();

            Map<String, Object> express = new HashMap<>();
            express.put("expressCode", order.getExpressCode());
            express.put("expressCompany", order.getExpressCompany());
            express.put("expressNo", order.getExpressesNo());

            data.add(express);

            for (BillOfLading billOfLading : billOfLadings) {
                Map<String, Object> item = new HashMap<>();
                item.put("expressCode", billOfLading.getExpressCode());
                item.put("expressCompany", billOfLading.getExpressCompany());
                item.put("expressNo", billOfLading.getExpressesNo());

                data.add(item);
            }

            return result.ok().inject(data);

        } catch (Exception e) {
            return result.fail().setMsg(e.getMessage());
        }
    }

    /**
     * 查询物流信息
     *
     * @param expressNo   快递单号
     * @param expressCode 快递公司编码
     */
    @GetMapping("/queryDeliveryDetail")
    public Result queryDeliveryDetail(@RequestParam String expressNo, @RequestParam String expressCode) {

        Result result = new Result();
        try {

            Express express = queryChannelService.findOne(QExpress.express.expressCompanyCode.eq(expressCode), Express.class);

            JSONObject item = new JSONObject();
            item.put("com", expressCode);
            item.put("num", expressNo);
            String param = item.toString();

            String customer = "54C47E7E32F6C71A37CA09D73E953119";
            String key = "MhDOdUjx726";
            String sign = MD5HashUtils.MD5(param + key + customer).toUpperCase();

            List<NameValuePair> postparams = new ArrayList<>();
            postparams.add(new BasicNameValuePair("param", param));
            postparams.add(new BasicNameValuePair("sign", sign));
            postparams.add(new BasicNameValuePair("customer", customer));

            String message = HttpRequests.postEntity("https://poll.kuaidi100.com/poll/query.do", postparams);

            JSONObject object = JSONObject.fromObject(message);
            Map<String, Object> data2 = new HashMap<>();
            data2.put("company", express.getName());
            data2.put("no", expressNo);

            if ("ok".equals(object.getString("message"))) {
                String data = object.getString("data");
                JSONArray logisticData = JSONArray.fromObject(data);
                List<Map<String, Object>> mapListJson = (List) logisticData;
                data2.put("data", mapListJson);
                return result.ok().inject(data2);
            } else {
                return result.ok().setMsg("暂无查询结果，请稍后再查").inject(data2);
            }

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 查看快递物流信息
     */
    @GetMapping("/orderDeliveryRecords")
    public Result orderDeliveryRecords(@RequestParam long id) {

        Result result = new Result();
        try {

            Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);

            JSONObject item = new JSONObject();
            item.put("com", order.getExpressCode());
            item.put("num", order.getExpressesNo());
            String param = item.toString();
            String customer = "54C47E7E32F6C71A37CA09D73E953119";
            String key = "MhDOdUjx726";
            String sign = MD5HashUtils.MD5(param + key + customer).toUpperCase();

            List<NameValuePair> postparams = new ArrayList<>();
            postparams.add(new BasicNameValuePair("param", param));
            postparams.add(new BasicNameValuePair("sign", sign));
            postparams.add(new BasicNameValuePair("customer", customer));

            String message = HttpRequests.postEntity("https://poll.kuaidi100.com/poll/query.do", postparams);

            JSONObject object = JSONObject.fromObject(message);
            Map<String, Object> data2 = new HashMap<>();
            data2.put("company", order.getExpressCompany());
            data2.put("no", order.getExpressesNo());

            if ("ok".equals(object.getString("message"))) {
                String data = object.getString("data");
                JSONArray logisticData = JSONArray.fromObject(data);
                List<Map<String, Object>> mapListJson = (List) logisticData;

                data2.put("data", mapListJson);
                return result.ok().inject(data2);
            } else {
                return result.ok().setMsg("暂无查询结果，请稍后再查").inject(data2);
            }

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 确认收货
     */
    @PutMapping("/receipt")
    public Result receipt(HttpServletRequest request, @RequestBody OrderDTO params) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            Order order = queryChannelService.findOne(QOrder.order.id.eq(params.getId()).and(QOrder.order.member.eq(member)), Order.class);
            orderApplication.receipt(order);

            return result.ok().inject(order);

        } catch (Exception e) {
            log.error("[确认收货异常]", e);
            return result.fail().setMsg("确认收货异常");
        }
    }

    /**
     * 取消订单
     */
    @PutMapping("/cancel")
    public Result cancel(HttpServletRequest request, @RequestBody OrderDTO params) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            Order order = queryChannelService.findOne(QOrder.order.id.eq(params.getId()).and(QOrder.order.member.eq(member)), Order.class);
            if (null == order) {
                return result.fail().setMsg("非法操作");
            }
            orderApplication.cancel(order, params.getNote());
            return result.ok();

        } catch (Exception e) {
            log.error("[取消订单异常]", e);
            return result.fail().setMsg("取消订单异常");
        }
    }

    /**
     * 取消拼团订单
     */
    @PutMapping("/cancelGroupBooking")
    public Result cancelGroupBooking(@RequestBody OrderDTO params) {

        Result result = new Result();
        try {

            GroupBookingOrder order = queryChannelService.findOne(QGroupBookingOrder.groupBookingOrder.id.eq(params.getId()), GroupBookingOrder.class);

            if (null == order) {
                return result.fail().setMsg("非法操作");
            }

            orderApplication.cancelGroupBooking(order);

            return result.ok();

        } catch (Exception e) {
            log.error("[取消拼团订单异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 取消原因
     */
    @GetMapping("/cancelCause")
    public Result cancelCause() {
        Result result = new Result();
        try {

            List<CancelCause> cancelCauses = queryChannelService.findAll(QCancelCause.cancelCause.status.eq(1), CancelCause.class);

            return result.ok().inject(cancelCauses);

        } catch (Exception e) {
            log.error("[获取取消原因列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 全部订单列表
     */
    @GetMapping("/list")

    public Result list(HttpServletRequest request, @RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "20") int pageSize, @RequestParam(defaultValue = "0") int status) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize);
            Map<String, Object> params = new HashMap<>();
            params.put("id", member.getId());

            String hql = builderHql("select o from Order o where 1=1 and o.member.id = :id ", params, status);
            QueryPage<Order> page = queryChannelService.findPage(hql, pageRequest.setParams(params), Order.class);

            for (Order order : page.getResult()) {

                if (order.getIsAfterSale() == 1) {
                    order.setOrderAfterSaleId(queryChannelService.findOne(QOrderAfterSale.orderAfterSale.order.id.eq(order.getId()), OrderAfterSale.class).getId());
                }

                if (null != order.getCoupon() && null != order.getCoupon().getComplimentaryGoods()) {
                    order.getCoupon().getComplimentaryGoods().setDefaultImage(storeDomain + "/uploads/" + order.getCoupon().getComplimentaryGoods().getDefaultImage());
                }

                if (order.getMarketingType() == 5) {
                    order.setPresellRetainagePayBeginTime(order.getDetails().get(0).getSku().getGoods().getPresellRetainagePayBeginTime());
                }

                for (OrderDetail detail : order.getDetails()) {
                    detail.setDefaultImage(storeDomain + "/uploads/" + detail.getDefaultImage());
                    detail.setGoodsId(detail.getSku().getGoods().getId());

                }

                //赠品活动订单
                if (order.getMarketingType() == 1) {
                    List<Goods> giftGoodses = queryChannelService.findAll("select g.goods from GiftGoods g where g.gift.id = :id ", ImmutableMap.of("id", order.getGiftActivity().getId()), Goods.class);

                    GiftActivity giftActivity = order.getGiftActivity();
                    giftActivity.setGiftGoodses(giftGoodses.stream().map(input -> {
                        Map<String, Object> data = new HashMap<>();
                        data.put("id", input.getId());
                        data.put("name", input.getName());
                        data.put("defaultImage", storeDomain + "/uploads/" + input.getDefaultImage());
                        return data;
                    }).collect(Collectors.toList()));

                    order.setGiftActivity(giftActivity);
                }
            }

            return result.ok().inject(ImmutableMap.of("page", page));

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    private String builderHql(String hql, Map<String, Object> params, int status) {
        if (status > 0) {
            hql += " and o.status = :status ";
            params.put("status", status);
        }

        hql += " order by o.createTime desc ";

        return hql;
    }


    /**
     * 提交订单
     */
    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    public Result submit(HttpServletRequest request, @RequestBody OrderDTO params) {
        Result result = new Result();
        try {

            WebUser member = queryChannelService.findOne(QWebUser.webUser.eq(Securitys.user(request)), WebUser.class);

            Requires.hasLength(member.getMobile(), "请先绑定手机号码");
            Requires.notEmpty(params.getDetails(), "此订单不支持购买");

            List<Order> orders = orderApplication.submit(member, params);

            double price = buildMoney(orders);
            if (price == 0) {
                orderApplication.shoppingCardPaySuccess(orders);
            }

            return result.ok().inject(ImmutableMap.of("orders", orders, "price", price, "time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));

        } catch (IllegalArgumentException | IllegalStateException | InterfaceException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }

    private double buildMoney(List<Order> orders) {
        double price = 0;
        for (Order order : orders) {
            price = ArithUtils.add(price, order.getMoney());
        }
        return price;
    }

    private double buildPrice(List<Order> orders) {
        double price = 0;
        for (Order order : orders) {
            price = ArithUtils.add(price, order.getPrice());
        }
        return price;
    }


    /**
     * 修改收货人，重新计算运费
     */
    @RequestMapping(value = "/totalFreightPrice", method = RequestMethod.PUT)
    public Result totalFreightPrice(HttpServletRequest request, @RequestBody OrderPreviewDTO orderPreview) {
        Result result = new Result();
        try {

            WebUser member = Securitys.user(request);
            List<Long> ids = orderPreview.getCarts().stream().map(ShopCartDTO::getId).collect(Collectors.toList());

            Set<Long> merchantIds = Sets.newHashSet();
            List<ShoppingCart> shoppingCarts = queryChannelService.findAll(QShoppingCart.shoppingCart.member.eq(member).and(QShoppingCart.shoppingCart.id.in(ids)), ShoppingCart.class);
            for (ShoppingCart cart : shoppingCarts) {
                merchantIds.add(cart.getSku().getGoods().getMerchant().getId());
            }

            List<WebUser> merchants = queryChannelService.findAll(QWebUser.webUser.id.in(merchantIds), WebUser.class);

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = new ArrayList<>();
            for (WebUser merchant : merchants) {

                MerchantShoppingCartGoodsDTO merchantShoppingCartGoods = new MerchantShoppingCartGoodsDTO();
                merchantShoppingCartGoods.setMerchantId(merchant.getId());
                merchantShoppingCartGoods.setMerchantName(merchant.getShopName());

                int goodsCount = 0;
                double subtotalPrice = 0.0;

                //会员领取的针对当前商品可用的购物卡
                List<ShoppingCardRecord> drawShoppingCardRecords = new ArrayList<>();
                //会员当前拥有的所有购物卡
                List<ShoppingCardRecord> userRecords = getUserRecords(member);

                List<ShoppingCart> carts = Lists.newArrayList();
                for (ShoppingCart cart : shoppingCarts) {
                    if (cart.getSku().getGoods().getMerchant().getId() == merchant.getId()) {
                        cart.setGoodsImage(storeDomain + "/uploads/" + cart.getGoodsImage());
                        goodsCount += cart.getQuantity();
                        subtotalPrice = ArithUtils.add(subtotalPrice, cart.getSubtotalPrice());
                        carts.add(cart);

                        merchantShoppingCartGoods.getCoupons().addAll(new UserCoupon(cart.getSku(), cart.getQuantity(), member, queryChannelService).getUsableDraw());
                        shopppingCardRecord(null, drawShoppingCardRecords, userRecords, cart.getSku());
                    }
                }

                merchantShoppingCartGoods.setGoodsCount(goodsCount);
                merchantShoppingCartGoods.setSubtotalPrice(subtotalPrice);
                merchantShoppingCartGoods.setShoppingCardRecords(drawShoppingCardRecords);

                merchantShoppingCartGoods.setGoodsList(carts);
                merchantGoodsList.add(merchantShoppingCartGoods);

            }

            DeliveryAddress deliveryAddress = new DeliveryAddress();
            deliveryAddress.setProvince(orderPreview.getProvince());
            deliveryAddress.setCity(orderPreview.getCity());

            return result.ok().inject(totalFreightPrice(deliveryAddress, merchantGoodsList));

        } catch (Exception e) {
            log.error("[计算运费异常]", e);
            return result.fail().setMsg("计算运费失败");
        }
    }


    /**
     * 立即购买计算运费
     */
    @RequestMapping(value = "/buyTotalFreightPrice", method = RequestMethod.PUT)
    public Result buyTotalFreightPrice(@RequestBody OrderPreviewDTO params, HttpServletRequest request) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(params.getId()), GoodsSku.class);
            //秒杀活动商品
            if (sku.getGoods().getMarketingType() == 2 && sku.getGoods().getSeckillStatus() == 5) {
                sku.setPrice(sku.getSeckillPrice());
            }

            //特价活动商品
            if (sku.getGoods().getMarketingType() == 1 && sku.getGoods().getBargainStatus() == 5) {
                sku.setPrice(sku.getBargainPrice());
            }

            //拼团活动商品
            if (sku.getGoods().getMarketingType() == 4 && sku.getGoods().getGroupBookingStatus() == 5 && params.getGroupBookingBuyType() != 1) {
                sku.setPrice(sku.getGroupBookingPrice());
            }

            //预售活动商品（开始支付定金）
            if (sku.getGoods().getMarketingType() == 3 && sku.getGoods().getPresellStatus() == 5) {
                sku.setPrice(ArithUtils.add(sku.getPresellSubscription(), sku.getPresellRetainage()));
            }

            //会员领取的针对当前商品可用的购物卡
            List<ShoppingCardRecord> drawShoppingCardRecords = new ArrayList<>();
            //会员当前拥有的所有购物卡
            List<ShoppingCardRecord> userRecords = getUserRecords(member);

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();
            MerchantShoppingCartGoodsDTO merchantShoppingCartGoods = new MerchantShoppingCartGoodsDTO();
            merchantShoppingCartGoods.setMerchantId(sku.getMerchant().getId());
            merchantShoppingCartGoods.setGoodsCount(params.getQuantity());

            List<ShoppingCart> carts = new ArrayList<>();

            ShoppingCart cart = new ShoppingCart();
            cart.setGoodsImage(storeDomain + "/uploads/" + sku.getGoods().getDefaultImage());
            cart.setGoodsName(sku.getGoods().getName());
            cart.setSkuNames(StringUtils.replace(sku.getSkuNames(), ",", " "));
            cart.setSku(sku);
            cart.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));
            cart.setQuantity(params.getQuantity());

            merchantShoppingCartGoods.getCoupons().addAll(new UserCoupon(cart.getSku(), cart.getQuantity(), member, queryChannelService).getUsableDraw());
            shopppingCardRecord(null, drawShoppingCardRecords, userRecords, cart.getSku());

            carts.add(cart);


            merchantShoppingCartGoods.setGoodsList(carts);
            merchantShoppingCartGoods.setShoppingCardRecords(drawShoppingCardRecords);
            merchantGoodsList.add(merchantShoppingCartGoods);

            DeliveryAddress deliveryAddress = new DeliveryAddress();
            deliveryAddress.setProvince(params.getProvince());
            deliveryAddress.setCity(params.getCity());

            return result.ok().inject(totalFreightPrice(deliveryAddress, merchantGoodsList));

        } catch (Exception e) {
            log.error("[计算运费异常]", e);
            return result.fail().setMsg("计算运费失败");
        }
    }

    /**
     * 去结算（订单预览）
     */
    @RequestMapping(value = "/preview", method = RequestMethod.POST)
    public Result preview(HttpServletRequest request, @RequestBody List<ShopCartDTO> params) {

        Result result = new Result();

        try {

            WebUser member = Securitys.user(request);
            List<Long> ids = params.stream().map(ShopCartDTO::getId).collect(Collectors.toList());

            Set<Long> merchantIds = new HashSet<>();
            List<ShoppingCart> shoppingCarts = queryChannelService.findAll(QShoppingCart.shoppingCart.member.eq(member).and(QShoppingCart.shoppingCart.id.in(ids)), ShoppingCart.class);
            for (ShoppingCart cart : shoppingCarts) {
                merchantIds.add(cart.getSku().getGoods().getMerchant().getId());
            }

            List<WebUser> merchants = queryChannelService.findAll(QWebUser.webUser.id.in(merchantIds), WebUser.class);

            DeliveryAddress deliveryAddress = queryChannelService.findOne(QDeliveryAddress.deliveryAddress.member.eq(member).and(QDeliveryAddress.deliveryAddress.defaultAddress.isTrue()), DeliveryAddress.class);

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = new ArrayList<>();

            for (WebUser merchant : merchants) {

                MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
                merchantItem.setMerchantId(merchant.getId());
                merchantItem.setMerchantName(merchant.getShopName());

                int goodsCount = 0;
                double subtotalPrice = 0.0;

                //会员领取的针对当前商品可用的优惠券
                List<Coupon> drawCoupons = new ArrayList<>();

                //会员领取的针对当前商品可用的购物卡
                List<ShoppingCardRecord> drawShoppingCardRecords = new ArrayList<>();

                //会员当前拥有的所有购物卡
                List<ShoppingCardRecord> userRecords = getUserRecords(member);

                List<ShoppingCart> carts = new ArrayList<>();
                List<GiftActivity> giftActivities = new ArrayList<>();
                List<GoodsSku> skus = new ArrayList<>();

                for (ShoppingCart cart : shoppingCarts) {

                    if (cart.getSku().getGoods().getMerchant().getId() == merchant.getId()) {

                        cart.setGoodsImage(storeDomain + "/uploads/" + cart.getGoodsImage());
                        cart.setGoodsId(cart.getSku().getGoods().getId());

                        goodsCount += cart.getQuantity();

                        //秒杀活动商品
                        if (cart.getSku().getGoods().getMarketingType() == 2) {
                            if (cart.getSku().getGoods().getSeckillStatus() == 5) {    //活动已开始
                                cart.setSubtotalPrice(ArithUtils.mul(cart.getSku().getSeckillPrice(), cart.getQuantity()));
                            } else {
                                cart.setSubtotalPrice(ArithUtils.mul(cart.getSku().getPrice(), cart.getQuantity()));
                            }
                        }

                        //特价活动商品
                        if (cart.getSku().getGoods().getMarketingType() == 1) {
                            if (cart.getSku().getGoods().getBargainStatus() == 5) {    //活动已开始
                                cart.setSubtotalPrice(ArithUtils.mul(cart.getSku().getBargainPrice(), cart.getQuantity()));
                            } else {
                                cart.setSubtotalPrice(ArithUtils.mul(cart.getSku().getPrice(), cart.getQuantity()));
                            }
                        }

                        //预售跟拼团商品非活动进行时，取普通价格
                        if ((cart.getSku().getGoods().getMarketingType() == 3 && cart.getSku().getGoods().getPresellStatus() != 5) || (cart.getSku().getGoods().getMarketingType() == 4 && cart.getSku().getGoods().getGroupBookingStatus() != 5)) {
                            cart.setSubtotalPrice(ArithUtils.mul(cart.getSku().getPrice(), cart.getQuantity()));
                        }

                        subtotalPrice = ArithUtils.add(subtotalPrice, cart.getSubtotalPrice());

                        cart.setSeckillStatus(cart.getSku().getGoods().getSeckillStatus());
                        cart.setGroupBookingStatus(cart.getSku().getGoods().getGroupBookingStatus());
                        cart.setBargainStatus(cart.getSku().getGoods().getBargainStatus());
                        cart.setMarketingType(cart.getSku().getGoods().getMarketingType());

                        carts.add(cart);

                        drawCoupons.addAll(new UserCoupon(cart.getSku(), cart.getQuantity(), member, queryChannelService).getUsableDraw());
                        shopppingCardRecord(deliveryAddress, drawShoppingCardRecords, userRecords, cart.getSku());

                        skus.add(cart.getSku());
                    }
                }

                giftActivity(skus, subtotalPrice, giftActivities);

                merchantItem.setGoodsCount(goodsCount);
                merchantItem.setSubtotalPrice(subtotalPrice);

                merchantItem.setGoodsList(carts);
                merchantItem.setWarehouseAddress(merchant.getWarehouseAddress());

                merchantItem.setCoupons(drawCoupons);
                merchantItem.setShoppingCardRecords(drawShoppingCardRecords);

                merchantItem.setGiftActivities(giftActivities);

                merchantGoodsList.add(merchantItem);

            }

            Map<String, Object> data = new HashMap<>();
            data.put("deliveryInfo", deliveryAddress);

            if (null == deliveryAddress) {
                data.put("merchants", merchantGoodsList);
            } else {
                data.put("merchants", totalFreightPrice(deliveryAddress, merchantGoodsList));
            }

            return result.ok().inject(data);

        } catch (Exception e) {
            log.error("[订单预览异常]", e);
            return result.fail().setMsg("订单预览异常");
        }

    }


    /**
     * 筛选出适用于当前购物车商品的购物卡并添加到适用购物卡列表
     *
     * @param deliveryAddress         收货地址
     * @param drawShoppingCardRecords 适用购物卡列表
     * @param userRecords             用户购物卡列表
     * @param sku                     当前购物车商品sku
     */
    private void shopppingCardRecord(DeliveryAddress deliveryAddress, List<ShoppingCardRecord> drawShoppingCardRecords, List<ShoppingCardRecord> userRecords, GoodsSku sku) {

        for (ShoppingCardRecord record : userRecords) {

            ShoppingCard card = record.getShoppingCard();

            boolean exist = false;
            for (ShoppingCardRecord drawShoppingCardRecord : drawShoppingCardRecords) {
                if (drawShoppingCardRecord.getId().equals(record.getId())) {
                    exist = true;
                    break;
                }
            }
            if (exist) {
                continue;
            }

            boolean flag = false;

            sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(sku.getId()), GoodsSku.class);
            GoodsChannel goodsChannel = sku.getGoods().getGoodsChannel().getParent().getParent();

            List<GoodsChannel> channels = queryChannelService.findAll("select c.goodsChannel from ShoppingCardChannel c where c.shoppingCard.id = :cid", ImmutableMap.of("cid", card.getId()), GoodsChannel.class);
            for (GoodsChannel channel : channels) {
                if (channel.getId() == goodsChannel.getId()) {
                    flag = true;
                    break;
                }
            }

            if (!flag) {
                continue;
            }
            flag = false;

            if (card.getAreaType() == 1 && card.getGoodsType() == 1 && card.getMerchantType() == 1) {
                drawShoppingCardRecords.add(record);
                continue;
            }

            if (card.getMerchantType() == 2) {
                //指定商家可以使用
                List<ShoppingCardMerchant> list = queryChannelService.findAll(QShoppingCardMerchant.shoppingCardMerchant.shoppingCard.id.eq(card.getId()), ShoppingCardMerchant.class);
                for (ShoppingCardMerchant shoppingCardMerchant : list) {
                    if (sku.getMerchant().getId() == shoppingCardMerchant.getMerchant().getId()) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    continue;
                }
                flag = false;
            }


            if (card.getGoodsType() == 2) {
                //指定商品可以使用
                List<ShoppingCardGoods> list = queryChannelService.findAll(QShoppingCardGoods.shoppingCardGoods.shoppingCard.id.eq(card.getId()), ShoppingCardGoods.class);
                for (ShoppingCardGoods shoppingCardGoods : list) {
                    if (sku.getGoods().getId() == shoppingCardGoods.getGoods().getId()) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    continue;
                }
                flag = false;
            }

            if (card.getAreaType() == 2) {
                //指定地区可以使用
                if (deliveryAddress == null) {
                    continue;
                }
                List<ShoppingCardAddress> list = queryChannelService.findAll(QShoppingCardAddress.shoppingCardAddress.shoppingCard.id.eq(card.getId()), ShoppingCardAddress.class);
                for (ShoppingCardAddress shoppingCardAddress : list) {
                    if (shoppingCardAddress.getProvince().equals(deliveryAddress.getProvince()) && shoppingCardAddress.getCity().equals(deliveryAddress.getCity()) && shoppingCardAddress.getArea().equals(deliveryAddress.getArea())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    continue;
                }
            }
            drawShoppingCardRecords.add(record);
        }
    }

    /**
     * 获取用户当前所有购物卡
     *
     * @param member 用户
     * @return 购物卡列表
     */
    private List<ShoppingCardRecord> getUserRecords(WebUser member) {
        List<ShoppingCardRecord> userRecords;
        userRecords = queryChannelService.findAll(QShoppingCardRecord.shoppingCardRecord.status.eq(1).and(QShoppingCardRecord.shoppingCardRecord.user.id.eq(member.getId())), ShoppingCardRecord.class);
        for (ShoppingCardRecord r : userRecords) {

            ShoppingCard card = r.getShoppingCard();
            if (card.getValidType() == 1) {
                card.setStartTime(DateFormatUtils.format(card.getValidStartTime(), "yyyy.MM.dd"));
                card.setEndTime(DateFormatUtils.format(card.getValidEndTime(), "yyyy.MM.dd"));
            }
            if (card.getGoodsType() == 2) {
                List<ShoppingCardGoods> goods = queryChannelService.findAll(QShoppingCardGoods.shoppingCardGoods.shoppingCard.id.eq(card.getId()), ShoppingCardGoods.class);
                List<Long> goodsIds = goods.stream().map(item -> item.getGoods().getId()).collect(Collectors.toList());
                r.setGoodsIds(goodsIds);
            }
        }
        return userRecords;
    }

    /**
     * 赠品活动
     */
    private void giftActivity(List<GoodsSku> skus, double subtotalPrice, List<GiftActivity> giftActivities) {

        for (GoodsSku sku : skus) {

            //赠品活动
            List<GiftActivity> merchantGiftActivities = queryChannelService.findAll(QGiftActivity.giftActivity.merchant.eq(sku.getGoods().getMerchant()).and(QGiftActivity.giftActivity.isValidity.eq(2)).and(QGiftActivity.giftActivity.status.eq(1)), GiftActivity.class);
            for (GiftActivity giftActivity : merchantGiftActivities) {
                //是否有设置全部商品可用的赠品活动
                if (giftActivity.getScopeGoodsType() == 1 && subtotalPrice >= giftActivity.getStandardsAmount()) {
                    giftActivities.add(giftActivity);
                }
                //是否有指定当前商品的赠品活动
                if (giftActivity.getScopeGoodsType() == 2 && subtotalPrice >= giftActivity.getStandardsAmount()) {
                    List<GiftScope> scopes = queryChannelService.findAll(QGiftScope.giftScope.merchant.eq(sku.getGoods().getMerchant()).and(QGiftScope.giftScope.gift.eq(giftActivity)), GiftScope.class);
                    for (GiftScope scope : scopes) {
                        if (scope.getGoods().getId() == sku.getGoods().getId()) {
                            giftActivities.add(giftActivity);
                        }
                    }
                }
                //是否有指定当前商品分类的赠品活动
                if (giftActivity.getScopeGoodsType() == 3 && subtotalPrice >= giftActivity.getStandardsAmount()) {
                    List<GiftChannel> channels = queryChannelService.findAll(QGiftChannel.giftChannel.merchant.eq(sku.getGoods().getMerchant()).and(QGiftChannel.giftChannel.gift.eq(giftActivity)), GiftChannel.class);
                    for (GiftChannel channel : channels) {
                        if (sku.getGoods().getGoodsChannel().getParent().getParent().getId() == channel.getChannel().getId()) {
                            giftActivities.add(giftActivity);
                        }
                    }
                }
            }

        }

        for (GiftActivity giftActivity : giftActivities) {
            List<Goods> gifts = queryChannelService.findAll("select g.goods from GiftGoods g where g.gift.id = :id and g.goods.store > 0 ", ImmutableMap.of("id", giftActivity.getId()), Goods.class);
            if (CollectionUtils.isNotEmpty(gifts)) {
                giftActivity.setGiftGoodses(gifts.stream().map(input -> {
                    Map<String, Object> data = new HashMap<>();
                    data.put("id", input.getId());
                    data.put("name", input.getName());
                    data.put("defaultImage", storeDomain + "/uploads/" + input.getDefaultImage());
                    return data;
                }).collect(Collectors.toList()));
            }
        }
    }

    /**
     * 立即购买
     */
    @RequestMapping(value = "/buy", method = RequestMethod.POST)
    public Result buy(HttpServletRequest request, @RequestBody ShopCartDTO params) {
        Result result = new Result();

        try {

            WebUser member = Securitys.user(request);
            GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(params.getId()), GoodsSku.class);

            //秒杀活动商品
            if (sku.getGoods().getMarketingType() == 2 && sku.getGoods().getSeckillStatus() == 5) {

                if (params.getQuantity() > sku.getSeckillStore()) {
                    return result.fail().setMsg("库存不足");
                }

                if (params.getQuantity() > sku.getSeckillLimit()) {
                    return result.fail().setMsg("超过限购数量");
                }

                sku.setPrice(sku.getSeckillPrice());

                List<OrderDetail> orders = queryChannelService.findAll("select d from OrderDetail d where d.sku.id = :id and d.order.marketingType = 4  and d.order.status !=6 and d.seckillSession.id = :sid and d.order.member.id = :mid", ImmutableMap.of("id", sku.getId(), "sid", sku.getGoods().getSeckillSession().getId(), "mid", member.getId()), OrderDetail.class);

                int quantitys = 0;

                for (OrderDetail orderDetail : orders) {
                    quantitys += orderDetail.getQuantity();
                }

                if (quantitys + params.getQuantity() > sku.getSeckillLimit()) {
                    return result.fail().setMsg("该商品限购" + sku.getSeckillLimit() + "，您暂无购买资格");
                }
            }


            //特价活动商品
            if (sku.getGoods().getMarketingType() == 1 && sku.getGoods().getBargainStatus() == 5) {

                if (params.getQuantity() > sku.getBargainStore()) {
                    return result.fail().setMsg("库存不足");
                }

                sku.setPrice(sku.getBargainPrice());
            }

            //拼团活动
            if (sku.getGoods().getMarketingType() == 4 && sku.getGoods().getGroupBookingStatus() == 5) {

                if (params.getQuantity() > sku.getStore()) {
                    return result.fail().setMsg("库存不足");
                }

                //商品参团购买
                if (params.getGroupBookingBuyType() != 1) {
                    sku.setPrice(sku.getGroupBookingPrice());
                }

            }

            //预售活动商品（开始支付定金）
            if (sku.getGoods().getMarketingType() == 3 && sku.getGoods().getPresellStatus() == 5) {

                if (params.getQuantity() > sku.getStore()) {
                    return result.fail().setMsg("库存不足");
                }

                sku.setPrice(ArithUtils.add(sku.getPresellSubscription(), sku.getPresellRetainage()));
            }

            WebUser merchant = sku.getMerchant();

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();

            MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
            merchantItem.setMerchantId(merchant.getId());
            merchantItem.setMerchantName(merchant.getShopName());
            merchantItem.setGoodsCount(params.getQuantity());
            merchantItem.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));
            merchantItem.setWarehouseAddress(merchant.getWarehouseAddress());

            DeliveryAddress deliveryAddress = queryChannelService.findOne(QDeliveryAddress.deliveryAddress.member.eq(member).and(QDeliveryAddress.deliveryAddress.defaultAddress.isTrue()), DeliveryAddress.class);


            //会员领取的针对当前商品可用的购物卡
            List<ShoppingCardRecord> drawShoppingCardRecords = Lists.newArrayList();

            //会员当前拥有的所有购物卡
            List<ShoppingCardRecord> userRecords = getUserRecords(member);

            List<ShoppingCart> carts = Lists.newArrayList();

            List<GiftActivity> giftActivities = Lists.newArrayList();

            ShoppingCart cart = new ShoppingCart();
            cart.setGoodsImage(storeDomain + "/uploads/" + sku.getGoods().getDefaultImage());
            cart.setGoodsId(sku.getGoods().getId());
            cart.setGoodsName(sku.getGoods().getName());
            cart.setSkuNames(StringUtils.replace(sku.getSkuNames(), ",", " "));
            cart.setSku(sku);

            cart.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));


            cart.setQuantity(params.getQuantity());
            cart.setMarketingType(sku.getGoods().getMarketingType());
            cart.setPresellStatus(sku.getGoods().getPresellStatus());
            cart.setPresellRetainagePayBeginTime(sku.getGoods().getPresellRetainagePayBeginTime());
            cart.setPresellRetainagePayEndTime(sku.getGoods().getPresellRetainagePayEndTime());

            cart.setSeckillStatus(sku.getGoods().getSeckillStatus());
            cart.setGroupBookingStatus(sku.getGoods().getGroupBookingStatus());
            cart.setBargainStatus(sku.getGoods().getBargainStatus());

            carts.add(cart);

            //获取当前商品可以使用的购物卡
            shopppingCardRecord(deliveryAddress, drawShoppingCardRecords, userRecords, cart.getSku());


            //赠品活动

            giftActivity(ImmutableList.of(cart.getSku()), cart.getSubtotalPrice(), giftActivities);

            merchantItem.setGoodsList(carts);
            merchantItem.setCoupons(new UserCoupon(sku, params.getQuantity(), member, queryChannelService).getUsableDraw());
            merchantItem.setShoppingCardRecords(drawShoppingCardRecords);
            merchantItem.setGiftActivities(giftActivities);

            merchantGoodsList.add(merchantItem);


            Map<String, Object> data = new HashMap<>();
            data.put("deliveryInfo", deliveryAddress);

            if (null == deliveryAddress) {
                data.put("merchants", merchantGoodsList);
            } else {
                data.put("merchants", totalFreightPrice(deliveryAddress, merchantGoodsList));
            }

            return result.ok().inject(data);

        } catch (Exception e) {
            log.error("[订单预览异常]", e);
            return result.fail().setMsg("订单预览异常");
        }

    }


    /**
     * 购买分销商品/申请分销商购买指定商品
     */
    @RequestMapping(value = "/buy/distribution", method = RequestMethod.POST)
    public Result buyDistribution(HttpServletRequest request, @RequestBody ShopCartDTO params) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(params.getId()), GoodsSku.class);
            WebUser merchant = sku.getMerchant();

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();
            MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
            merchantItem.setMerchantId(merchant.getId());
            merchantItem.setMerchantName(merchant.getShopName());
            merchantItem.setGoodsCount(params.getQuantity());
            merchantItem.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));
            merchantItem.setWarehouseAddress(merchant.getWarehouseAddress());

            DeliveryAddress deliveryAddress = queryChannelService.findOne(QDeliveryAddress.deliveryAddress.member.eq(member).and(QDeliveryAddress.deliveryAddress.defaultAddress.isTrue()), DeliveryAddress.class);

            List<ShoppingCart> carts = Lists.newArrayList();

            ShoppingCart cart = new ShoppingCart();
            cart.setGoodsImage(storeDomain + "/uploads/" + sku.getGoods().getDefaultImage());
            cart.setGoodsId(sku.getGoods().getId());
            cart.setGoodsName(sku.getGoods().getName());
            cart.setSkuNames(StringUtils.replace(sku.getSkuNames(), ",", " "));
            cart.setSku(sku);

            cart.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));

            cart.setQuantity(params.getQuantity());
            cart.setMarketingType(sku.getGoods().getMarketingType());
            cart.setPresellStatus(sku.getGoods().getPresellStatus());
            cart.setPresellRetainagePayBeginTime(sku.getGoods().getPresellRetainagePayBeginTime());
            cart.setPresellRetainagePayEndTime(sku.getGoods().getPresellRetainagePayEndTime());

            cart.setSeckillStatus(sku.getGoods().getSeckillStatus());
            cart.setGroupBookingStatus(sku.getGoods().getGroupBookingStatus());
            cart.setBargainStatus(sku.getGoods().getBargainStatus());

            carts.add(cart);
            merchantItem.setGoodsList(carts);

            merchantGoodsList.add(merchantItem);

            Map<String, Object> data = new HashMap<>();
            data.put("deliveryInfo", deliveryAddress);

            if (null == deliveryAddress) {
                data.put("merchants", merchantGoodsList);
            } else {
                data.put("merchants", totalFreightPrice(deliveryAddress, merchantGoodsList));
            }

            return result.ok().inject(data);

        } catch (Exception e) {
            log.error("[订单预览异常]", e);
            return result.fail().setMsg("订单预览异常");
        }
    }


    /**
     * 提交订单
     */
    @RequestMapping(value = "/submit/distribution", method = RequestMethod.POST)
    public Result submitDistribution(HttpServletRequest request, @RequestBody OrderDTO params) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            Requires.hasLength(member.getMobile(), "请先绑定手机号码");
            Requires.notEmpty(params.getDetails(), "此订单不支持购买");

            if (params.getOrderType() == 1 && member.getDistributor() != null) {
                Requires.isTrue(params.getLevel() > member.getDistributor().getLevel().getLevel(), "无法申请更低等级的分销商");
            }

            List<Order> orders = orderApplication.submitDistribution(member, params);
            double price = buildMoney(orders);

            return result.ok().inject(ImmutableMap.of("orders", orders, "price", price, "time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));

        } catch (IllegalArgumentException | InterfaceException | IllegalStateException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }


    /**
     * 购买直播商品
     */
    @RequestMapping(value = "/buy/live", method = RequestMethod.POST)
    public Result buyLive(HttpServletRequest request, @RequestBody ShopCartDTO params) {

        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(params.getId()), GoodsSku.class);
            WebUser merchant = sku.getMerchant();

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = new ArrayList<>();
            MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
            merchantItem.setMerchantId(merchant.getId());
            merchantItem.setMerchantName(merchant.getShopName());
            merchantItem.setGoodsCount(params.getQuantity());
            merchantItem.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));
            merchantItem.setWarehouseAddress(merchant.getWarehouseAddress());

            DeliveryAddress deliveryAddress = queryChannelService.findOne(QDeliveryAddress.deliveryAddress.member.eq(member).and(QDeliveryAddress.deliveryAddress.defaultAddress.isTrue()), DeliveryAddress.class);

            List<ShoppingCart> carts = Lists.newArrayList();

            ShoppingCart cart = new ShoppingCart();
            cart.setGoodsImage(storeDomain + "/uploads/" + sku.getGoods().getDefaultImage());
            cart.setGoodsId(sku.getGoods().getId());
            cart.setGoodsName(sku.getGoods().getName());
            cart.setSkuNames(StringUtils.replace(sku.getSkuNames(), ",", " "));
            cart.setSku(sku);

            cart.setSubtotalPrice(ArithUtils.mul(sku.getPrice(), params.getQuantity()));

            cart.setQuantity(params.getQuantity());
            cart.setMarketingType(sku.getGoods().getMarketingType());
            cart.setPresellStatus(sku.getGoods().getPresellStatus());
            cart.setPresellRetainagePayBeginTime(sku.getGoods().getPresellRetainagePayBeginTime());
            cart.setPresellRetainagePayEndTime(sku.getGoods().getPresellRetainagePayEndTime());

            cart.setSeckillStatus(sku.getGoods().getSeckillStatus());
            cart.setGroupBookingStatus(sku.getGoods().getGroupBookingStatus());
            cart.setBargainStatus(sku.getGoods().getBargainStatus());

            carts.add(cart);
            merchantItem.setGoodsList(carts);

            merchantGoodsList.add(merchantItem);

            Map<String, Object> data = new HashMap<>();
            data.put("deliveryInfo", deliveryAddress);

            if (null == deliveryAddress) {
                data.put("merchants", merchantGoodsList);
            } else {
                data.put("merchants", totalFreightPrice(deliveryAddress, merchantGoodsList));
            }

            return result.ok().inject(data);

        } catch (Exception e) {
            log.error("[订单预览异常]", e);
            return result.fail().setMsg("订单预览异常");
        }
    }


    /**
     * 提交直播订单
     */
    @RequestMapping(value = "/submit/live", method = RequestMethod.POST)
    public Result submitOrder(HttpServletRequest request, @RequestBody OrderDTO params) {
        Result result = new Result();
        try {

            WebUser member = Securitys.user(request);

            List<Order> orders = orderApplication.submitLiveOrder(member, params);
            double price = buildMoney(orders);

            return result.ok().inject(ImmutableMap.of("orders", orders, "price", price, "time", DateUtil.formatDateTime(new Date())));

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取商品sku异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 计算运费
     */
    private List<MerchantShoppingCartGoodsDTO> totalFreightPrice(DeliveryAddress deliveryAddress, List<MerchantShoppingCartGoodsDTO> goodsList) {

        for (MerchantShoppingCartGoodsDTO item : goodsList) {

            WebUser merchant = queryChannelService.findOne(QWebUser.webUser.id.eq(item.getMerchantId()), WebUser.class);
            double freightPrice = 0;

            List<ShoppingCart> result = new ArrayList<>();
            Map<Long, Integer> nummbers = new HashMap<>();
            Map<Long, Double> grams = new HashMap<>();

            for (ShoppingCart shoppingCart : item.getGoodsList()) {
                if (nummbers.containsKey(shoppingCart.getSku().getGoods().getId())) {
                    int quantity = nummbers.get(shoppingCart.getSku().getGoods().getId());
                    nummbers.put(shoppingCart.getSku().getGoods().getId(), quantity + shoppingCart.getQuantity());

                } else {

                    nummbers.put(shoppingCart.getSku().getGoods().getId(), shoppingCart.getQuantity());
                    grams.put(shoppingCart.getSku().getGoods().getId(), shoppingCart.getSku().getGoods().getGram());
                    result.add(shoppingCart);
                }
            }

            for (ShoppingCart shoppingCart : result) {
                int quantity = nummbers.get(shoppingCart.getSku().getGoods().getId());
                shoppingCart.setCount(quantity);

                double gram = grams.get(shoppingCart.getSku().getGoods().getId());
                shoppingCart.getSku().getGoods().setGram(gram);
            }
            for (ShoppingCart shoppingCart : result) {

                Goods goods = shoppingCart.getSku().getGoods();
                if (shoppingCart.getCount() != 0) {

                    //运费模板
                    if (goods.getPostageType() == 1) {

                        MerchantFreight freight = queryChannelService.findOne(QMerchantFreight.merchantFreight.city.eq(deliveryAddress.getCity()).and(QMerchantFreight.merchantFreight.merchant.eq(merchant).and(QMerchantFreight.merchantFreight.template.id.eq(goods.getFreightTemplate().getId()))), MerchantFreight.class);

                        MerchantFreightTemplate template = queryChannelService.findOne(QMerchantFreightTemplate.merchantFreightTemplate.id.eq(goods.getFreightTemplate().getId()), MerchantFreightTemplate.class);

                        //按重量
                        if (template.getType() == 1) {
                            double gram = ArithUtils.mul(goods.getGram(), shoppingCart.getCount());//总重量

                            if (null != freight) {   //拿到了模板内设置的区域运费
                                if (gram <= freight.getFirstWeight()) {
                                    freightPrice += freight.getFirstWeightAmount();
                                } else {
                                    double fistWeightAmount = freight.getFirstWeightAmount();
                                    double weight = ArithUtils.sub(gram, freight.getFirstWeight());

                                    if (weight < freight.getOtherWeight()) {
                                        freightPrice += ArithUtils.add(fistWeightAmount, freight.getOtherWeightAmount());
                                    } else {
                                        freightPrice += ArithUtils.add(fistWeightAmount, ArithUtils.mul(Math.ceil(ArithUtils.div(weight, freight.getOtherWeight(), 2)), freight.getOtherWeightAmount()));
                                    }
                                    //                                    freightPrice += ArithUtils.add(freight.getFirstWeightAmount(), ArithUtils.mul(ArithUtils.div(ArithUtils.sub(gram, freight.getFirstWeight()), freight.getOtherWeight(), 2), freight.getOtherWeightAmount()));
                                }

                            } else {

                                if (gram <= template.getDefaultWeight()) {
                                    freightPrice += template.getDefaultWeightAmount();
                                } else {

                                    double fistWeightAmount = template.getDefaultWeightAmount();
                                    double weight = ArithUtils.sub(gram, template.getDefaultWeight());

                                    if (weight < template.getDefaultAddWeight()) {
                                        freightPrice += ArithUtils.add(fistWeightAmount, template.getDefaultAddWeightAmount());
                                    } else {
                                        freightPrice += ArithUtils.add(fistWeightAmount, ArithUtils.mul(Math.ceil(ArithUtils.div(weight, template.getDefaultAddWeight(), 2)), template.getDefaultAddWeightAmount()));
                                    }
                                    //                                    freightPrice += ArithUtils.add(template.getDefaultWeightAmount(), ArithUtils.mul(ArithUtils.div(ArithUtils.sub(gram, template.getDefaultWeight()), template.getDefaultAddWeight(), 2), template.getDefaultAddWeightAmount()));
                                }

                            }

                        }

                        //按件
                        if (template.getType() == 2) {

                            if (null != freight) {

                                if (shoppingCart.getCount() <= freight.getFirstPiece()) {
                                    freightPrice += freight.getFirstPieceAmount();
                                } else {
                                    freightPrice += ArithUtils.add(freight.getFirstPieceAmount(), ArithUtils.mul(ArithUtils.sub(shoppingCart.getCount(), freight.getFirstPiece()), freight.getOtherPieceAmount()));
                                }

                            } else {

                                if (shoppingCart.getCount() <= template.getDefaultPiece()) {
                                    freightPrice += template.getDefaultPieceAmount();
                                } else {
                                    freightPrice += ArithUtils.add(template.getDefaultPieceAmount(), ArithUtils.mul(ArithUtils.sub(shoppingCart.getCount(), template.getDefaultPiece()), template.getDefaultAddPieceAmount()));
                                }

                            }

                        }

                    } else if (goods.getPostageType() == 2) {
                        freightPrice += ArithUtils.add(freightPrice, 0);
                    } else if (goods.getPostageType() == 3) {        //指定运费
                        freightPrice += ArithUtils.add(freightPrice, ArithUtils.mul(goods.getPostage(), shoppingCart.getCount()));
                    }
                }
            }
            item.setFreightPrice(freightPrice);
        }
        return goodsList;
    }


    /**
     * 统计订单数量
     */
    @GetMapping("/count")
    public Result count(HttpServletRequest request) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            int count1 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 1", ImmutableMap.of("mid", member.getId()));
            int count2 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 2", ImmutableMap.of("mid", member.getId()));
            int count3 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 3", ImmutableMap.of("mid", member.getId()));
            int count4 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 4", ImmutableMap.of("mid", member.getId()));
            int count5 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and isAfterSale = 1", ImmutableMap.of("mid", member.getId()));

            return result.ok().inject(ImmutableMap.of("count1", count1, "count2", count2, "count3", count3, "count4", count4, "count5", count5));

        } catch (Exception e) {
            log.error("[订单统计异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 提交预售订单
     */
    @RequestMapping(value = "/submitPresell", method = RequestMethod.POST)
    public Result submitPresell(HttpServletRequest request, @RequestBody OrderDTO params) {

        Result result = new Result();
        try {

            WebUser member = queryChannelService.findOne(QWebUser.webUser.eq(Securitys.user(request)), WebUser.class);

            if (Strings.isNullOrEmpty(member.getMobile())) {
                return result.fail().setMsg("请先绑定手机号码");
            }

            if (params.getDetails().isEmpty()) {
                return result.fail().setMsg("此订单不支持购买");
            }

            Order order = orderApplication.submitPresellOrder(member, params);

            return result.ok().inject(ImmutableMap.of("order", order, "price", order.getPrepaidDepositPrice(), "time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));

        } catch (Exception e) {

            if (e instanceof InterfaceException) {
                return result.fail().setMsg(e.getMessage());
            }

            if (e instanceof IllegalStateException) {
                return result.fail().setMsg(e.getMessage());
            }

            log.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }


    /**
     * 提交拼团开团订单
     */
    @RequestMapping(value = "/submitGroupBooking", method = RequestMethod.POST)

    public Result submitGroupBookind(HttpServletRequest request, @RequestBody OrderDTO params) {
        Result result = new Result();
        try {

            WebUser member = queryChannelService.findOne(QWebUser.webUser.eq(Securitys.user(request)), WebUser.class);

            if (Strings.isNullOrEmpty(member.getMobile())) {
                return result.fail().setMsg("请先绑定手机号码");
            }

            if (params.getDetails().isEmpty()) {
                return result.fail().setMsg("此订单不支持购买");
            }

            GroupBookingOrder order = orderApplication.submitGroupBookingOrder(member, params);

            return result.ok().inject(ImmutableMap.of("order", order, "price", order.getPrice(), "time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));

        } catch (Exception e) {

            if (e instanceof InterfaceException) {
                return result.fail().setMsg(e.getMessage());
            }

            if (e instanceof IllegalStateException) {
                return result.fail().setMsg(e.getMessage());
            }

            log.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }

    /**
     * 我的拼团订单列表
     */
    @GetMapping("/groupBookingOrders")

    public Result groupBookingOrders(HttpServletRequest request, @RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "20") int pageSize, @RequestParam(defaultValue = "0") int status) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize);
            Map<String, Object> params = new HashMap<>();
            params.put("id", member.getId());


            String hql = builderGroupBookingHql("select o.groupBooking from GroupBookingOrder o where o.member.id = :id and o.status not in (1,5) ", params, status);
            QueryPage<GroupBooking> page = queryChannelService.findPage(hql, pageRequest.setParams(params), GroupBooking.class);

            page.setResult(page.getResult().stream().peek(groupBooking -> {
                groupBooking.setDefaultImage(storeDomain + "/uploads/" + groupBooking.getDefaultImage());
                GroupBookingOrder order = queryChannelService.findOne("select o from GroupBookingOrder o where o.groupBooking.id = :gid and o.member.id = :uid and o.status in (2,3,4) ", ImmutableMap.of("gid", groupBooking.getId(), "uid", member.getId()), GroupBookingOrder.class);
                if (null != order) {
                    groupBooking.setId(order.getId());
                    groupBooking.setDetails(ImmutableList.of(order));
                }
            }).collect(Collectors.toList()));
            return result.ok().inject(ImmutableMap.of("page", page));

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    private String builderGroupBookingHql(String hql, Map<String, Object> params, int status) {

        if (status > 0) {
            hql += " and o.groupBooking.status = :status ";
            params.put("status", status);
        }

        hql += " order by o.createTime desc ";

        return hql;
    }


    /**
     * 拼团订单详情
     */
    @GetMapping("/groupBookingOrderDetail")
    public Result groupBookingOrderDetail(@RequestParam("id") long id) {

        Result result = new Result();
        try {
            GroupBookingOrder order = queryChannelService.findOne(QGroupBookingOrder.groupBookingOrder.id.eq(id), GroupBookingOrder.class);
            order.getGroupBooking().setDefaultImage(storeDomain + "/uploads/" + order.getGroupBooking().getDefaultImage());
            GroupBooking groupBooking = order.getGroupBooking();
            List<GroupBookingOrder> orders = queryChannelService.findAll(QGroupBookingOrder.groupBookingOrder.groupBooking.eq(order.getGroupBooking()).and(QGroupBookingOrder.groupBookingOrder.status.in(2, 3, 4)), GroupBookingOrder.class);
            for (GroupBookingOrder groupBookingOrder : orders) {
                groupBookingOrder.setAvatar(storeDomain + "/avatar/" + groupBookingOrder.getMember().getAvatar());
                groupBookingOrder.setNickname(groupBookingOrder.getMember().getNickname());
                groupBookingOrder.setMemberId(groupBookingOrder.getMember().getId());
            }
            groupBooking.setDetails(orders);
            groupBooking.setSystemTime(new Date().getTime());

            return result.ok().inject(groupBooking);

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 分享拼团
     */
    @GetMapping("/shareGroupBookingDetail")
    public Result shareGroupBookingDetail(HttpServletRequest request, @RequestParam("id") long id) {

        Result result = new Result();
        try {

            GroupBookingOrder order = queryChannelService.findOne(QGroupBookingOrder.groupBookingOrder.id.eq(id), GroupBookingOrder.class);
            order.getGroupBooking().setDefaultImage(storeDomain + "/uploads/" + order.getGroupBooking().getDefaultImage());
            GroupBooking groupBooking = order.getGroupBooking();
            List<GroupBookingOrder> orders = queryChannelService.findAll(QGroupBookingOrder.groupBookingOrder.groupBooking.eq(order.getGroupBooking()).and(QGroupBookingOrder.groupBookingOrder.status.in(2, 3, 4)), GroupBookingOrder.class);
            for (GroupBookingOrder groupBookingOrder : orders) {
                groupBookingOrder.setAvatar(null != groupBookingOrder.getMember().getAvatar() ? storeDomain + "/avatar/" + groupBookingOrder.getMember().getAvatar() : null);
                groupBookingOrder.setNickname(groupBookingOrder.getMember().getNickname());
                groupBookingOrder.setMemberId(groupBookingOrder.getMember().getId());
                groupBookingOrder.setGoodsId(groupBookingOrder.getSku().getGoods().getId());
            }
            groupBooking.setDetails(orders);
            groupBooking.setSystemTime(new Date().getTime());
            groupBooking.setGroupBookinges(builderGroupBookings(request));
            groupBooking.setGoodsId(groupBooking.getSku().getGoods().getId());


            return result.ok().inject(groupBooking);

        } catch (Exception e) {
            log.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 拼团的记录
     */
    private List<Map<String, Object>> builderGroupBookings(HttpServletRequest request) {

        List<Map<String, Object>> data = Lists.newArrayList();

        if (Securitys.isLogin(request)) {

            WebUser member = Securitys.user(request);
            List<GroupBooking> groupBookings = queryChannelService.findLimit("select g from GroupBooking g where g.status = 1 ", new QueryPageRequest().setPageSize(2), GroupBooking.class);

            for (GroupBooking groupBooking : groupBookings) {
                Map<String, Object> item = new HashMap<>();
                item.put("id", groupBooking.getId());
                item.put("avatar", null != groupBooking.getMember().getAvatar() ? storeDomain + "/avatar/" + groupBooking.getMember().getAvatar() : null);
                item.put("nickname", groupBooking.getMember().getNickname());
                item.put("endTime", groupBooking.getEndTime());
                item.put("groupBookingCondition", groupBooking.getGroupBookingCondition() - groupBooking.getGroupBookingTotal());
                item.put("specs", groupBooking.getSku().getAttribute1().getName() + " " + (null != groupBooking.getSku().getAttribute2() ? groupBooking.getSku().getAttribute2().getName() : ""));
                item.put("skuId", groupBooking.getSku().getId());
                item.put("goodsId", groupBooking.getSku().getGoods().getId());

                List<GroupBookingOrder> orders = queryChannelService.findAll(QGroupBookingOrder.groupBookingOrder.groupBooking.eq(groupBooking).and(QGroupBookingOrder.groupBookingOrder.status.in(2, 3)), GroupBookingOrder.class);

                List<Map<String, Object>> detail = Lists.newArrayList();
                for (GroupBookingOrder order : orders) {

                    if (member.getId() == order.getMember().getId()) {
                        continue;
                    }

                    Map<String, Object> orderItem = new HashMap<>();
                    orderItem.put("avatar", null != order.getMember().getAvatar() ? storeDomain + "/avatar/" + order.getMember().getAvatar() : null);
                    orderItem.put("nickname", order.getMember().getNickname());
                    orderItem.put("type", order.getType());
                    orderItem.put("goodsId", order.getSku().getGoods().getId());
                    detail.add(orderItem);
                }
                item.put("details", detail);

                data.add(item);
            }

        }

        return data;
    }

}
